package fanalg;

import com.martiansoftware.jsap.FlaggedOption;
import com.martiansoftware.jsap.JSAP;
import com.martiansoftware.jsap.JSAPException;
import com.martiansoftware.jsap.JSAPResult;
import com.martiansoftware.jsap.Switch;

/**
 * @author Tomasz Werszko
 *
 */
public class FAN {
	/*
	 * variables storing execution options
	 */
	private static JSAP jsap;
	private static JSAPResult COMMANDS;
	
	private static void registerParameters(String[] args) throws JSAPException{
		FAN.jsap = new JSAP();
	    	    
	    Switch sw1 = new Switch("help")
								.setShortFlag('h')
								.setLongFlag("help");
	    sw1.setHelp("Prints help.");
	    jsap.registerParameter(sw1);
	    
	    Switch sw2 = new Switch("verbose")
								.setShortFlag('v')
								.setLongFlag("verbose");
	    sw2.setHelp("Prints more information during the search.");
	    jsap.registerParameter(sw2);
	    
	    Switch sw3 = new Switch("details")
								.setShortFlag('c')
								.setLongFlag("circuit-details");
	    sw3.setHelp("Prints information about the circuit.");
	    jsap.registerParameter(sw3);
	    
	    FlaggedOption opt1 = new FlaggedOption("file")
        										.setStringParser(JSAP.STRING_PARSER)
        										.setDefault("") 
        										.setRequired(true) 
        										.setShortFlag('f') 
        										.setLongFlag("file");
	    opt1.setHelp("A path to a file with circuit in blif format"); 
	    jsap.registerParameter(opt1);

	    FlaggedOption opt2 = new FlaggedOption("fault")
												.setStringParser(JSAP.STRING_PARSER)
												.setDefault("") 
												.setRequired(true) 
												.setShortFlag('s') 
												.setLongFlag("stuck-at");
	    opt2.setHelp("Name of the gate with a fault"); 
	    jsap.registerParameter(opt2);
	    
	    FlaggedOption opt3 = new FlaggedOption("faultType")
												.setStringParser(JSAP.STRING_PARSER)
												.setDefault("") 
												.setRequired(true) 
												.setShortFlag('t') 
												.setLongFlag("fault-type");
	    opt3.setHelp("Type of the fault (1 for s-a-1 or 0 for s-a-0)"); 
	    jsap.registerParameter(opt3);

	    COMMANDS = jsap.parse(args);
	        
	    // check whether the command line was valid, and if it wasn't,
	    // display usage information and exit.
	    if (!COMMANDS.success()) {
	    	FAN.printHelp();
	        System.exit(1);
	    }
	}
	
	/**
	 * Prints help
	 */
	private static void printHelp(){
		System.err.println();
        System.err.println("Usage: java -jar podem.jar");// + FAN.class.getName());
        System.err.println("                " + jsap.getUsage());
        System.err.println();
        System.err.println(FAN.jsap.getHelp());
        System.err.println("Authors: Bartosz Woronicz (mistrzipan@gmail.com)");
        System.err.println("         Tomasz Werszko (twerszko@gmail.com)");
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//parsing command line arguments
		try{
			registerParameters(args);
		}catch(JSAPException ex){
			System.exit(1);
		}
		
		//printing help
		if(COMMANDS.getBoolean("help") || args.length == 0){
			FAN.printHelp();
			System.exit(1);
		}
		
		//getting file name
		String fileName = COMMANDS.getString("file");
	    
	    //creating representation of the circuit
	    Circuit circuit = null;
	    try{
	    	circuit = new Circuit(fileName);
	    }catch(ParserException ex){
	    	System.out.print("Parsing error: ");
	    	if(ex.line > 0){
	    		System.out.println("at line " + ex.line + ".");
	    	}
	    	if(!ex.message.equals("")){
	    		System.out.println(ex.message);
	    	}
	    	//ex.printStackTrace();
	    	System.exit(1);	
	    }catch(Exception ex){
	    	System.out.println("IO error trying to read the file!");
	    	//ex.printStackTrace();
	    	System.exit(1);	
	    }
	    
	    //verbose
		if(COMMANDS.getBoolean("verbose")){
			circuit.verbose = true;
		}
		
		//circuit details
		if(COMMANDS.getBoolean("details")){
			System.out.println("------------------------------");
			System.out.println("Model name: " + circuit.getModelName());
			System.out.println("Primary inputs: " + circuit.getPrimatyInputs());
			System.out.println("Primary outputs: " + circuit.getPrimatyOutputs());
			System.out.println("Elements: ");
			System.out.println(circuit.getEntities());
			System.out.println("------------------------------");
			//System.out.println(circuit.getConnectionNet());
		}
		
	    //getting fault position and type
	    String fault = COMMANDS.getString("fault");
	    if(!circuit.entities.containsKey(fault)){
	    	System.out.println("Wrong fault position.");
	    	System.exit(1);
	    }
	    
	    String faultType = COMMANDS.getString("faultType");
	    if(!(faultType.equals("0") || faultType.equals("1"))){
	    	System.out.println("Wrong fault type.");
	    	System.exit(1);
	    }
	    
	    LogicSystem faultTypeLog;
	    if(faultType.equals("0")){
	    	faultTypeLog = LogicSystem.D;
	    }else{
	    	faultTypeLog = LogicSystem.notD;
	    }
	    
	    if(circuit.verbose == true){
	    	System.out.println("------------------------------");
	    	System.out.println("Start.");
	    	System.out.println("------------------------------");
	    }
	    boolean result = false;
	    try{
	    	result = circuit.findTest(fault, fault, faultTypeLog);
	    }catch(Exception e){
	    	System.out.println("Error while searching for a test.");
	    	e.printStackTrace();
	    	System.exit(1);	
	    }
	    if(result == true){
	    	System.out.println("Test was found!");
	    	System.out.println("Inputs:");
	    	System.out.println(circuit.inputsToString());
	    	System.out.println("Outputs:");
	    	System.out.println(circuit.outputsToString());
	    }else{
	    	System.out.println("No test was found.");
	    }
	    
	    /*System.out.println(circuit.xPathCheck("d"));
	    
	    LogicSystem log[] = {LogicSystem.FALSE, LogicSystem.D};
	    Gate g = (Gate)circuit.getEntity("d");
	    System.out.println(circuit.imply("d", log));
	    System.out.println(circuit.xPathCheck("d"));
	    System.out.println(g.outValue);
	    String string = new String();
		String string2 = new String();
		int i = 0;
		for(LogicSystem val : g.inValues){
			string += val.toString() + " ";
			string2 += g.inputs[i].toString() + " ";
			i++;
		}
		System.out.println(string2);
		System.out.println(string);*/
	}

}
